/*
s * 描          述:  <描述>
 * 修  改   人:  Administrator
 * 修改时间:  2014年5月11日
 * <修改描述:>
 */
package com.tx.component.file.context;

import java.io.File;
import java.io.InputStream;
import java.util.List;
import java.util.stream.Collectors;

import org.springframework.beans.factory.InitializingBean;
import org.springframework.web.multipart.MultipartFile;

import com.tx.component.file.catalog.VitualFileCatalog;
import com.tx.component.file.resource.FCResource;
import com.tx.core.exceptions.util.AssertUtils;

/**
 * 文件处理容器<br/>
 * 利用该容器能够实现存放文件<br/>
 * 获取文件<br/>
 * 存放临时文件<br/>
 * 自动清理临时文件<br/>
 * 获取临时文件流<br/>
 * ... ...<br/>
 * 不建议在该封装中对业务逻辑相关查询进行支撑<br/>
 * 文件容器对文件的获取最好都是find的逻辑关系<br/>
 * 文件容器，作为控件支撑系统中的文件存放逻辑<br/>
 *
 * @author Rain.he
 * @version [版本号, 2015年3月12日]
 * @see [相关类/方法]
 * @since [产品/模块版本]
 */
public class FileContext extends FileContextBuilder
        implements FileEngine, InitializingBean {
    
    /** 文件容器自我引用 */
    public static FileEngine engine;
    
    /**
     * 获取文件容器句柄<br/>
     * <功能详细描述>
     * @return [参数说明]
     * 
     * @return FileContext [返回类型说明]
     * @exception throws [异常类型] [异常说明]
     * @see [类、类#方法、类#成员]
     */
    public static FileEngine getEngine() {
        if (FileContext.engine != null) {
            return FileContext.engine;
        }
        synchronized (FileContext.class) {
            FileContext.engine = applicationContext.getBean(beanName,
                    FileContext.class);
        }
        AssertUtils.notNull(FileContext.engine, "engine is null.");
        
        return FileContext.engine;
    }
    
    /**
     * @return
     */
    @Override
    public List<String> getCatalogs() {
        List<String> catalogs = this.catalogMap.keySet()
                .stream()
                .collect(Collectors.toList());
        return catalogs;
    }
    
    /**
     * @param catalog
     * @return
     */
    @Override
    public VitualFileCatalog getVitualFileCatalog(String catalog) {
        AssertUtils.notEmpty(catalog, "catalog is empty.");
        VitualFileCatalog c = doGetCatalog(catalog);
        return c;
    }
    
    /**
     * @param catalog
     * @param relativePath
     * @param input
     * @return
     */
    @Override
    public FCResource save(VitualFileCatalog vfc, String relativePath,
            InputStream inputStream) {
        AssertUtils.notNull(vfc, "vitualFileCatalog is empty.");
        AssertUtils.notEmpty(relativePath, "relativePath is empty.");
        AssertUtils.notNull(inputStream, "inputStream is null.");
        
        FCResource res = vfc.getResource(relativePath);
        res.save(inputStream);
        
        return res;
    }
    
    /**
     * @param catalog
     * @param relativePath
     * @param input
     * @return
     */
    @Override
    public FCResource save(VitualFileCatalog vfc, String relativePath,
            MultipartFile multipartFile) {
        AssertUtils.notNull(vfc, "vitualFileCatalog is empty.");
        AssertUtils.notEmpty(relativePath, "relativePath is empty.");
        AssertUtils.notNull(multipartFile, "multipartFile is null.");
        
        FCResource res = vfc.getResource(relativePath);
        res.save(multipartFile);
        
        return res;
    }
    
    /**
     * @param vfc
     * @param relativePath
     * @param file
     * @return
     */
    @Override
    public FCResource save(VitualFileCatalog vfc, String relativePath,
            File file) {
        AssertUtils.notNull(vfc, "vitualFileCatalog is empty.");
        AssertUtils.notEmpty(relativePath, "relativePath is empty.");
        AssertUtils.notNull(file, "file is null.");
        
        FCResource res = vfc.getResource(relativePath);
        res.save(file);
        
        return res;
    }
    
    /**
     * @param catalog
     * @param relativePath
     * @param input
     * @return
     */
    @Override
    public FCResource add(VitualFileCatalog vfc, String relativePath,
            InputStream inputStream) {
        AssertUtils.notNull(vfc, "vitualFileCatalog is empty.");
        AssertUtils.notEmpty(relativePath, "relativePath is empty.");
        AssertUtils.notNull(inputStream, "inputStream is null.");
        
        FCResource res = vfc.getResource(relativePath);
        res.add(inputStream);
        
        return res;
    }
    
    /**
     * @param vfc
     * @param relativePath
     * @param multipartFile
     * @return
     */
    @Override
    public FCResource add(VitualFileCatalog vfc, String relativePath,
            MultipartFile multipartFile) {
        AssertUtils.notNull(vfc, "vitualFileCatalog is empty.");
        AssertUtils.notEmpty(relativePath, "relativePath is empty.");
        AssertUtils.notNull(multipartFile, "multipartFile is null.");
        
        FCResource res = vfc.getResource(relativePath);
        res.add(multipartFile);
        
        return res;
    }
    
    /**
     * @param vfc
     * @param relativePath
     * @param file
     * @return
     */
    @Override
    public FCResource add(VitualFileCatalog vfc, String relativePath,
            File file) {
        AssertUtils.notNull(vfc, "vitualFileCatalog is empty.");
        AssertUtils.notEmpty(relativePath, "relativePath is empty.");
        AssertUtils.notNull(file, "file is null.");
        
        FCResource res = vfc.getResource(relativePath);
        res.add(file);
        
        return res;
    }
    
    /**
     * @param catalog
     * @param relativePath
     * @return
     */
    @Override
    public void delete(VitualFileCatalog vfc, String relativePath) {
        AssertUtils.notNull(vfc, "vitualFileCatalog is empty.");
        AssertUtils.notEmpty(relativePath, "relativePath is empty.");
        
        FCResource res = vfc.getResource(relativePath);
        res.delete();
    }
    
    /**
     * @param catalog
     * @param relativePath
     * @return
     */
    @Override
    public FCResource find(VitualFileCatalog vfc, String relativePath) {
        AssertUtils.notNull(vfc, "vitualFileCatalog is empty.");
        AssertUtils.notEmpty(relativePath, "relativePath is empty.");
        
        FCResource res = vfc.getResource(relativePath);
        return res;
    }
    
    /**
     * @param catalog
     * @param relativePath
     * @return
     */
    @Override
    public List<FCResource> query(VitualFileCatalog vfc, String relativePath) {
        AssertUtils.notNull(vfc, "vitualFileCatalog is empty.");
        AssertUtils.notEmpty(relativePath, "relativePath is empty.");
        
        FCResource res = vfc.getResource(relativePath);
        return res.findFiles();
    }
    
    /**
     * @param catalog
     * @param relativePath
     * @return
     */
    @Override
    public List<FCResource> children(VitualFileCatalog vfc,
            String relativePath) {
        AssertUtils.notNull(vfc, "vitualFileCatalog is empty.");
        AssertUtils.notEmpty(relativePath, "relativePath is empty.");
        
        FCResource res = vfc.getResource(relativePath);
        return res.getChildren();
    }
    
    /**
     * @param sourceCatalog
     * @param targetCatalog
     */
    @Override
    public void copy(String sourceCatalog, String targetCatalog) {
        AssertUtils.notEmpty(sourceCatalog, "sourceCatalog is empty.");
        AssertUtils.notEmpty(targetCatalog, "targetCatalog is empty.");
        
        VitualFileCatalog source = doGetCatalog(sourceCatalog);
        AssertUtils.notNull(source, "catalog:{} is not exist.", sourceCatalog);
        VitualFileCatalog target = doGetCatalog(targetCatalog);
        AssertUtils.notNull(target, "catalog:{} is not exist.", targetCatalog);
        
        //source.getResource(relativePath)
    }
    
}
